﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DataCodeDemo.Servers
{
    public class SocketTcpServer: SocketObject
    {
        private Socket _socket;
        private IPAddress _host;//IP地址
        private int _port;//端口
        private bool _isStop;//停止标志
        private byte[] result = new byte[1024];//接收缓存区
        private Dictionary<string, Socket> dicSockets = new Dictionary<string, Socket>();//客户端字典

        public override void InitSocket(IPAddress ip, int port)
        {
            _host = ip;
            _port = port;
        }

        public override void InitSocket(string ip, int port)
        {
            _host = IPAddress.Parse(ip);
            _port = port;
        }

        public override int Start()
        {
            _isStop = false;
            try
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _socket.Bind(new IPEndPoint(_host, _port));
                _socket.Listen(100);//设定最多100个排队连接请求
                Thread AcceptTh = new Thread(ListenClientConnect);//通过多线程监听客户端连接
                AcceptTh.Start();
                return 1;
            }
            catch (Exception ex)
            {
                return -1;
            }
        }

        private void ListenClientConnect()
        {
            while (true)
            {
                if (_isStop) break;
                try
                {
                    Socket clientSocket = _socket?.Accept();
                    if (!dicSockets.ContainsKey(clientSocket.RemoteEndPoint.ToString()))//如果不包含就创建新的通信套接字
                    {
                        dicSockets.Add(clientSocket.RemoteEndPoint.ToString(), clientSocket);
                        clientSocket.Send(Encoding.UTF8.GetBytes("connected" + Environment.NewLine));
                        Thread receiveTh = new Thread(ReceiveMessage);
                        receiveTh.Start(clientSocket);
                    }
                }
                catch
                {
                    return;
                }
                Thread.Sleep(1);
            }
        }

        private void ReceiveMessage(object clientSocket)
        {
            Socket client = (Socket)clientSocket;
            byte[] data = new byte[1024 * 1024];
            while (true)
            {
                if (client == null || client.Connected == false)
                {
                    dicSockets.Remove(client.ToString());
                    break;
                }
                int realen = 0;//客户端数据长度
                try
                {
                    realen = client.Receive(data, 0, data.Length, SocketFlags.None);
                }
                catch (Exception e)
                {
                    //异常退出                  
                    StopConnecte(client);
                    dicSockets.Remove(client.ToString());
                    break;
                }
                //client.Send(Encoding.UTF8.GetBytes("1" + Environment.NewLine));
                if (realen <= 0)
                {
                    //对方正常退出                   
                    StopConnecte(client);
                    dicSockets.Remove(client.ToString());
          
                    break;
                }
                //接受到的数据
                //string fromClientMsg = Encoding.Default.GetString(data, 0, realen);
                byte[] fromClientBytes = data.Take(realen).ToArray();
                InvokeRecvMsg(this, new RecvMsgEventArgs {
                    ClientSocket=client,
                    Msg=fromClientBytes
                });
            }
        }

        private void StopConnecte(Socket client)
        {
            try
            {
                if (client.Connected)
                {
                    client?.Shutdown(SocketShutdown.Both);
                    client?.Close(100);
                }
            }
            catch (Exception ex)
            {

            }
        }

        public override void Stop()
        {
            foreach (var dicSocket in dicSockets)
            {
                StopConnecte(dicSocket.Value);
            }
            _isStop = true;
            _socket?.Close();
            //_socket = null;
        }

        public void Send(string clientIp,byte[] data)
        {
            try
            {
                Socket client = dicSockets.FirstOrDefault(o => o.Key == clientIp).Value;
                if (client == null) return;         
                else
                {
                    if (!client.Connected)
                    {
                        client?.Close(100);
                        dicSockets.Remove(client.ToString());
                    }
                    else
                    {
                        client.Send(data);
                    }
                }
                
            }
            catch (Exception ex)
            {

            }
        }

        public void Send(Socket client, byte[] data)
        {
            try
            {
                if (client == null) return;           
                else
                {
                    if (!client.Connected)
                    {
                        client?.Close(100);
                        dicSockets.Remove(client.ToString());
                    }
                    else
                    {
                        client.Send(data);
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }

       
    }
}
